package me.seawenc.db.migration.service;


import java.util.Map;
import java.util.stream.Collectors;
import me.seawenc.db.migration.bean.DatabaseBean;
import me.seawenc.db.migration.bean.ExecParameters;
import me.seawenc.db.migration.bean.TableBean;
import me.seawenc.db.migration.helper.YmlHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MigrationService {
    Logger logger = LogManager.getLogger(MigrationService.class);
    DatabaseService srcDbService;
    DatabaseService targetDbService;
    private DatabaseBean srcDatabase;

    // 将源数据库转为中间对象
    private DatabaseBean srcLogicDatabase;

    // 当前的目标库信息，只用于做数据检查
    private DatabaseBean targetDatabase;
    // 通过将src库转为的目标数据库
    private DatabaseBean srcToTargetDatabase;

    DataxService dataxService;

    ExecParameters parameters;

    public MigrationService(ExecParameters parameters) throws Exception {
        this.parameters=parameters;
        srcDbService=new DatabaseService(parameters.getConfigPath(),"migration.src.jdbc.");
        srcDatabase = srcDbService.buildDatabaseStructure(true);
        targetDbService=new DatabaseService(parameters.getConfigPath(),"migration.target.jdbc.");
        targetDatabase = targetDbService.buildDatabaseStructure(false);
    }

    /**
     * 检查数据库是否需要升级
     */
    public void check(){
        // fixme
        // 1.检查数据库类型是否支持

        // 2.检查数据库版本是否支持

        // 3.检查目标数据库中的表是已存在，migrate-ddl=true时检查,若存在则退出

        // 4.检查源库表于目标库表是否一致，migrate-ddl=false时检查，若不一致，则退出
    }

    /**
     * 迁移数据库结构
     */
    public void migrationDbStructure() throws Exception {
        String migrateDdl = YmlHelper.getConfig(parameters.getConfigPath(), "migration.migrate-ddl","true");
        String migrateDdlExec = YmlHelper.getConfig(parameters.getConfigPath(), "migration.migrate-ddl-exec","true");
        if(!"true".equals(migrateDdl)){
            logger.warn("migrate-ddl配置为false，不迁移数据库结构");
            return;
        }
        if(srcLogicDatabase.getDbType()!=targetDatabase.getDbType()){
            // 将数据转换网状结构转为星型结构降低系统难度，先将对象转为逻辑对象后再转为目标物理对象
            srcLogicDatabase= srcDbService.physicalToLogicModel(srcDatabase);
            // 再将逻辑对象转为目标物理对象, fixme 内部逻辑未完成
            srcToTargetDatabase= targetDbService.logicModelToPhysical(srcLogicDatabase);
        }else{
            // 源库类型与目标库类型一致时,无需转换
            srcToTargetDatabase= srcDatabase;
        }

        String sqls=targetDbService.buildPhysicalDdlSql(srcToTargetDatabase);
        // fixme 写入sql文件

        // fixme 执行ddl-sql

        logger.warn("暂不支持,请使用其它方式进行ddl同步");
    }

    /**
     * 数据迁移前检查
     * @throws Exception
     */
    public boolean migrationDbDataBeforeCheck() throws Exception {
        Map<String, TableBean> targetMap = targetDatabase.getDbTables().stream().collect(Collectors.toMap(t -> t.getTableName(), t -> t));

        boolean result = true;
        logger.info(String.format("\033[1;30;42m|%3s| %31s | %12s | %15s | %13s |\033[0m","#","表名","目标表存在","目标表有数","源表/目标表字段数"));
        for (int i = 0; i < srcDatabase.getDbTables().size(); i++) {
            TableBean src=srcDatabase.getDbTables().get(i);
            TableBean target = targetMap.get(src.getTableName());
            if(target==null){
                logger.info(String.format("|%3s| %31s | %27s | %16s | %16s |",i,src.getTableName(),"\u001B[1;31mN\u001B[0m","-",src.getFields().size()+"/-"));
                result=false;
                continue;
            }
            boolean hasData = targetDbService.dbEngine.hasData(src.getTableName());
            boolean hasSameField = src.getFields().size()==target.getFields().size();
            String hasDataFormat = hasData ? " %16s ":"\u001B[31m %16s \u001B[0m";
            String hasSameFieldFormat= hasSameField?" %16s ":"\u001B[31m %16s \u001B[0m";
            // 字段数不等
            if(hasData || !hasSameField){
                result=false;
            }
            logger.info(String.format("|%3s| %31s | %16s | "+hasDataFormat +" | "+hasSameFieldFormat+" |",i,src.getTableName(),"Y",hasData?"Y":"N",src.getFields().size()+"/"+target.getFields().size()));
        }

        String cResult=result?"\u001B[1;32m成功\u001B[0m":"\u001B[1;31m失败\u001B[0m";
        logger.info(String.format("数据迁移前检查\u001B[31m %s \u001B[0m(以上表格中存在红色的表)",cResult));

        return result;
    }

    /**
     * 迁移数据库数据
     */
    public void migrationDbData() throws Exception {
        String migrateData = YmlHelper.getConfig(parameters.getConfigPath(), "migration.migrate-data","true");
        if(!"true".equals(migrateData)){
            System.out.println("migrate-data配置为false，不迁移数据");
            return;
        }
        dataxService = new DataxService(parameters, srcDatabase, targetDatabase);
        dataxService.dataxMigration();
    }
}
